﻿Imports System.Web.UI
Imports System.ComponentModel
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports System.Collections.Specialized

Namespace Controls
    <ParseChildren(True, "Items"), Description("Disuz WebControl TabControl"), ToolboxData("<{0}:TabControl runat=server></{0}:TabControl>"), DefaultEvent("TabSelectedIndexChanged"), DesignTimeVisible(True), PersistChildren(False), _
    Designer(GetType(TabControlDesigner))> _
    Public Class TabControl
        Inherits WebControl
        Implements IPostBackDataHandler
        Implements IPostBackEventHandler
        Implements INamingContainer

        Shared Sub New()
            TabControl.TabSelectedIndexChangedEvent = New Object()
        End Sub

        Public Sub New()
            Me.SelectedTab = New HtmlInputHidden()
            Me._SelectedIndex = -1
            Me.SelectedTab.Value = String.Empty
            Me._Width = Unit.Pixel(350)
            Me._Height = Unit.Pixel(150)
            Me._Items = New TabPageCollection(Me)
            Me._SelectionMode = SelectionModeEnum.Client

            Me.Height = Unit.Pixel(100)
            Me.Width = Unit.Pixel(100)
            Me._HeightUnitMode = HeightUnitEnum.percent
            Me._WidthUnitMode = WidthUnitEnum.percent

            Me.LeftOffSetX = 0
        End Sub

#Region "声明事件处理"

        Private Shared ReadOnly TabSelectedIndexChangedEvent As Object

        Public Custom Event TabSelectedIndexChanged As EventHandler
            AddHandler(ByVal value As EventHandler)
                MyBase.Events.[AddHandler](TabControl.TabSelectedIndexChangedEvent, value)
            End AddHandler
            RemoveHandler(ByVal value As EventHandler)
                MyBase.Events.[RemoveHandler](TabControl.TabSelectedIndexChangedEvent, value)
            End RemoveHandler
            RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)

            End RaiseEvent
        End Event

#End Region

        Protected Overloads Overrides Sub AddParsedSubObject(ByVal parsedObj As Object)
            If TypeOf parsedObj Is TabPage Then
                Me.Items.Add(DirectCast(parsedObj, TabPage))
            End If
        End Sub



        Protected Overloads Overrides Sub CreateChildControls()
            'this.Controls.Clear(); 
            Me.CreateControlCollection()
            Me.SelectedTab.ID = Me.UniqueID
            For i As Integer = 0 To Me.Items.Count - 1
                Me.Controls.Add(Me.Items(i))
            Next
            MyBase.ChildControlsCreated = True
            MyBase.CreateChildControls()
        End Sub

        Protected Overloads Overrides Sub OnPreRender(ByVal args As EventArgs)
            MyBase.OnPreRender(args)
            Dim i As Integer = Me.SelectedIndex
            If i <> -1 Then
                Me.Items(i).Selected = True
                Me.SelectedTab.Value = Me.Items(i).UniqueID
            Else
                Me.SelectedTab.Value = String.Empty
            End If

            Dim output As String = String.Format("<SCRIPT language=""javascript"" src=""{0}""></SCRIPT>" & Chr(13) & "" & Chr(10) & "<LINK href=""{1}"" type=""text/css"" rel=""stylesheet"">" & Chr(13) & "" & Chr(10) & "", TabScriptPath, TabCssPath)
#If NET1 Then
        If Not Page.IsClientScriptBlockRegistered("TabWindow") Then 
            Page.RegisterClientScriptBlock("TabWindow", output) 
        End If 
#Else
            If Not Page.ClientScript.IsClientScriptBlockRegistered("TabWindow") Then
                Page.ClientScript.RegisterClientScriptBlock(Me.[GetType](), "TabWindow", output)
            End If
#End If

            MyBase.OnPreRender(args)
        End Sub

        Protected Sub OnTabSelectedIndexChanged(ByVal e As EventArgs)
            If MyBase.Events IsNot Nothing Then
                Dim handler1 As EventHandler = DirectCast(MyBase.Events(TabSelectedIndexChangedEvent), EventHandler)
                RaiseEvent TabSelectedIndexChanged(Me, e)
            End If
        End Sub

        Protected Overloads Overrides Sub Render(ByVal pOutPut As HtmlTextWriter)
            If LeftOffSetX > 0 Then
                pOutPut.Write("<div Class=""tabs"" ID=""" + Me.UniqueID + "_Tab"" style=""padding-left:" + LeftOffSetX + ";"">")
            Else
                pOutPut.Write("<div Class=""tabs"" ID=""" + Me.UniqueID + "_Tab"" >")
            End If

            Me.SelectedTab.RenderControl(pOutPut)
            pOutPut.Write("<ul>")
            Me.RenderTabButton(pOutPut)
            pOutPut.Write("</ul></div><div id=""" + Me.UniqueID + "tabarea"" class=""tabarea"">")
            Me.RenderTabContent(pOutPut)
            pOutPut.Write("</div>")
        End Sub

        Friend Sub RenderDownLevelContent(ByVal output As HtmlTextWriter)
            Me.Render(output)
        End Sub

        Private Sub RenderTabButton(ByVal pOutPut As HtmlTextWriter)
            If Me.SelectionMode = SelectionModeEnum.Server Then
                For i As Integer = 0 To Me.Items.Count - 1
                    If Me.Items(i).Selected Then
                        pOutPut.Write("<li class=""CurrentTabSelect"" ><a href=""#"" class=""current"" onfocus=""this.blur();"">" + Me.Items(i).Caption + "</a></li>")
                    Else

#If NET1 Then
                    pOutPut.Write("<li class=""TabSelect"" onmouseover=""tabpage_mouseover(this)"" onmouseout=""tabpage_mouseout(this)"" onClick=""tabpage_selectonserver(this,'" + Me.Items(i).UniqueID + "');" + Me.Page.GetPostBackEventReference(Me, "") + """><a href=""#"" onfocus=""this.blur();"">" + Me.Items(i).Caption + "</a></li>") 
#Else
#End If
                        pOutPut.Write("<li class=""TabSelect"" onmouseover=""tabpage_mouseover(this)"" onmouseout=""tabpage_mouseout(this)"" onClick=""tabpage_selectonserver(this,'" + Me.Items(i).UniqueID + "');" + Me.Page.ClientScript.GetPostBackEventReference(Me, "") + """><a href=""#"" onfocus=""this.blur();"">" + Me.Items(i).Caption + "</a></li>")
                    End If
                Next
            Else
                For i As Integer = 0 To Me.Items.Count - 1
                    If Me.Items(i).Selected Then
                        pOutPut.Write("<li id=""" + Me.Items(i).UniqueID + "_li"" class=""CurrentTabSelect"" onclick=""tabpage_selectonclient(this,'" + Me.Items(i).UniqueID + "');""><a href=""#"" class=""current"" onfocus=""this.blur();"">" + Me.Items(i).Caption + "</a></li>")
                    Else
                        pOutPut.Write("<li id=""" + Me.Items(i).UniqueID + "_li"" class=""TabSelect"" onmouseover=""tabpage_mouseover(this)"" onMouseOut=""tabpage_mouseout(this)"" onclick=""tabpage_selectonclient(this,'" + Me.Items(i).UniqueID + "');""><a href=""#"" onfocus=""this.blur();"">" + Me.Items(i).Caption + "</a></li>")
                    End If
                Next
            End If
        End Sub

        Private Sub RenderTabContent(ByVal pOutPut As HtmlTextWriter)
            For i As Integer = 0 To Me.Items.Count - 1
                Me.Items(i).RenderControl(pOutPut)
            Next
        End Sub

        Private Function LoadPostData(ByVal ControlDataKey As String, ByVal PostBackDataCollection As NameValueCollection) As Boolean Implements IPostBackDataHandler.LoadPostData
            Dim postbackdata As String = PostBackDataCollection(ControlDataKey)
            If (postbackdata IsNot Nothing) AndAlso (postbackdata <> Me.SelectedTabPageID) Then
                Me.SelectedTabPageID = postbackdata
                Return True
            End If
            Return False
        End Function

        Private Sub RaisePostDataChangedEvent() Implements IPostBackDataHandler.RaisePostDataChangedEvent
            Me.OnTabSelectedIndexChanged(EventArgs.Empty)
        End Sub

        Private Sub RaisePostBackEvent(ByVal pEventArgument As String) Implements IPostBackEventHandler.RaisePostBackEvent
        End Sub


        <MergableProperty(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), PersistenceMode(PersistenceMode.InnerDefaultProperty)> _
        Public ReadOnly Property Items() As TabPageCollection
            Get
                Return Me._Items
            End Get
        End Property

        <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public Property SelectedIndex() As Integer
            Get
                If Me.Items.Count <= 0 Then
                    Return (Me._SelectedIndex = -1)
                End If
                If Me._SelectedIndex = -1 Then
                    For i As Integer = 0 To Me.Items.Count - 1
                        If Me.Items(i).Visible AndAlso (Me.Items(i).UniqueID = Me.SelectedTabPageID) Then
                            Return (Me._SelectedIndex = i)
                        End If
                    Next
                    Return (Me._SelectedIndex = 0)
                End If
                If Me._SelectedIndex >= Me.Items.Count Then
                    Return (Me._SelectedIndex = 0)
                End If
                Return Me._SelectedIndex
            End Get
            Set(ByVal value As Integer)
                If (value < -1) OrElse (value >= Me.Items.Count) Then
                    Throw New ArgumentOutOfRangeException("选项页必须小于" + Me.Items.Count.ToString())
                End If
                Me._SelectedIndex = value
            End Set
        End Property

        Protected Property SelectedTabPageID() As String
            Get
                If Me.ViewState("SelectedTabPageID") IsNot Nothing Then
                    Return DirectCast(Me.ViewState("SelectedTabPageID"), String)
                End If
                Return String.Empty
            End Get
            Set(ByVal value As String)
                Me.ViewState("SelectedTabPageID") = value
            End Set
        End Property


        <Description("Javascript脚本文件所在目录。"), DefaultValue("./")> _
        Public Property TabScriptPath() As String
            Get
                Dim obj As Object = ViewState("TabScriptPath")
                Return IIf(obj Is Nothing, "../js/tabstrip.js", DirectCast(obj, String))
            End Get
            Set(ByVal value As String)
                ViewState("TabScriptPath") = value
            End Set
        End Property


        <Description("css文件所在目录。"), DefaultValue("./")> _
        Public Property TabCssPath() As String
            Get
                Dim obj As Object = ViewState("TabCssPath")
                Return IIf(obj Is Nothing, "../styles/tab.css", DirectCast(obj, String))
            End Get
            Set(ByVal value As String)
                ViewState("TabCssPath") = value
            End Set
        End Property



        <Description("顶部属性页标题距左边偏移量"), DefaultValue(0)> _
        Public Property LeftOffSetX() As Integer
            Get
                Dim obj As Object = ViewState("LeftOffSetX")
                Return IIf(obj Is Nothing, 0, CInt(obj.ToString()))
            End Get
            Set(ByVal value As Integer)
                ViewState("LeftOffSetX") = value
            End Set
        End Property


        ''' <summary> 
        ''' 初始化创建tabpage页 
        ''' 此方法主要解决datagrid 控件 的DataGrid_ItemCreated方法创建分页时其parent.parent (tabcontrol)为空从而导致无法分页(在.net1下这个方法可以不调用) 
        ''' 请在page中的InitializeComponent使用 
        ''' </summary> 
        Public Sub InitTabPage()
            CreateChildControls()
        End Sub


#Region "其它设置选项"

        Public Property SelectionMode() As SelectionModeEnum
            Get
                Return Me._SelectionMode
            End Get
            Set(ByVal value As SelectionModeEnum)
                Me._SelectionMode = value
            End Set
        End Property


        Public Property HeightUnitMode() As HeightUnitEnum
            Get
                Return Me._HeightUnitMode
            End Get
            Set(ByVal value As HeightUnitEnum)
                Me._HeightUnitMode = value
            End Set
        End Property

        Public Property WidthUnitMode() As WidthUnitEnum
            Get
                Return Me._WidthUnitMode
            End Get
            Set(ByVal value As WidthUnitEnum)
                Me._WidthUnitMode = value
            End Set
        End Property


        Private _HeightUnitMode As HeightUnitEnum
        Private _WidthUnitMode As WidthUnitEnum
        Private _Height As Unit
        Private _Items As TabPageCollection
        Private _SelectedIndex As Integer
        Private _SelectionMode As SelectionModeEnum
        Private _Width As Unit
        Private SelectedTab As HtmlInputHidden

        Public Enum HeightUnitEnum
            percent
            px
        End Enum

        Public Enum WidthUnitEnum
            percent
            px
        End Enum


        Public Enum SelectionModeEnum
            Client
            Server
        End Enum

#End Region

    End Class
End Namespace